﻿/*
Copyright (c) 2010 Vratislav Cermak (vratacermak@gmail.com)
 
This file is part of TeachMe Project. See http://code.google.com/p/teach-me for more information.
 
TeachMe is an open source project. Using of TeachMe is free of charge.
It is distributed under GNU General Public License version 3 (GPLv3).
GPLv3 can be found at http://www.gnu.org/licenses/gpl.html.
 
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the license for more details.
*/

using System;
using System.Windows.Forms;
using TeachMe.Application.Configuration;
using TeachMe.Application.Properties;

namespace TeachMe.Application.Forms.Options
{
    public partial class OptionsForm : PseudoModalForm
    {
        private interface IOptionsControlDescriptor
        {
            void Create();

            OptionsControl Instance { get; }
        }

        private class OptionsControlDescriptor<T> : IOptionsControlDescriptor where T : OptionsControl, new()
        {
            private T _instance;

            public void Create()
            {
                _instance = new T();
            }

            public OptionsControl Instance
            {
                get { return _instance; }
            }
        }

        private readonly Root _root;
        private IOptionsControlDescriptor _current;

        public OptionsForm(Root root)
        {
            _root = root;
            _root.UserSettings.CheckOut();
            _root.ImportExcludes.CheckOut();

            InitializeComponent();

            WindowProportions.Lock(this, _root.MachineSettings);

            _root.HotkeysManager.UnregisterAll();

            tvMain.Nodes.Add(Resources.General).Tag = new OptionsControlDescriptor<General>();
            TreeNode entries = tvMain.Nodes.Add(Resources.Entries);
            entries.Tag = new OptionsControlDescriptor<Entries>();
            entries.Nodes.Add(Resources.Priorities).Tag = new OptionsControlDescriptor<Priorities>();
            entries.Nodes.Add(Resources.Appearance).Tag = new OptionsControlDescriptor<Appearance>();
            tvMain.Nodes.Add(Resources.Intervals).Tag = new OptionsControlDescriptor<Intervals>();
            tvMain.Nodes.Add(Resources.Hotkeys).Tag = new OptionsControlDescriptor<Hotkeys>();
            tvMain.Nodes.Add(Resources.Import).Tag = new OptionsControlDescriptor<Options.Import>();

            tvMain.ExpandAll();

            if (!String.IsNullOrEmpty(_root.MachineSettings.LastOptionsNode))
            {
                SelectNodeByName(tvMain.Nodes, _root.MachineSettings.LastOptionsNode);
            }
            if (tvMain.SelectedNode == null && tvMain.Nodes != null && tvMain.Nodes.Count > 0)
            {
                tvMain.SelectedNode = tvMain.Nodes[0];
            }
        }

        private void SelectNodeByName(TreeNodeCollection nodes, string name)
        {
            foreach (TreeNode node in nodes)
            {
                if (String.Compare(node.Text, name, true) == 0)
                {
                    tvMain.SelectedNode = node;

                    break;
                }

                if (node.Nodes != null && node.Nodes.Count > 0)
                {
                    SelectNodeByName(node.Nodes, name);
                }
            }
        }

        private void OnAfterSelect(object sender, TreeViewEventArgs e)
        {
            IOptionsControlDescriptor descriptor = e.Node.Tag as IOptionsControlDescriptor;
            if (descriptor == null)
            {
                throw new InvalidOperationException();
            }
            
            _current = descriptor;

            if (descriptor.Instance == null)
            {
                descriptor.Create();
                if (descriptor.Instance == null)
                {
                    throw new InvalidOperationException();
                }
                descriptor.Instance.Root = _root;
                descriptor.Instance.Parent = container.Panel2;
                descriptor.Instance.Dock = DockStyle.Fill;
                //
                descriptor.Instance.LoadOptions();
            }

            descriptor.Instance.Show();
        }

        private void OnBeforeSelect(object sender, TreeViewCancelEventArgs e)
        {
            if (_current != null && _current.Instance != null)
            {
                _current.Instance.Hide();
            }
        }

        private void SaveOptions()
        {
            RecursiveSave(tvMain.Nodes);
        }

        private static void RecursiveSave(TreeNodeCollection nodes)
        {
            foreach (TreeNode node in nodes)
            {
                IOptionsControlDescriptor descriptor = node.Tag as IOptionsControlDescriptor;
                if (descriptor == null)
                {
                    throw new InvalidOperationException();
                }
                if (descriptor.Instance != null)
                {
                    descriptor.Instance.SaveOptions();
                }

                if (node.Nodes != null && node.Nodes.Count > 0)
                {
                    RecursiveSave(node.Nodes);
                }
            }
        }

        private void OnApplyClick(object sender, EventArgs e)
        {
            SaveOptions();

            _root.UserSettings.CheckIn(true);
            _root.ImportExcludes.CheckIn(true);
        }

        private void OnOkClick(object sender, EventArgs e)
        {
            SaveOptions();
        }

        private void OnFormClosed(object sender, FormClosedEventArgs e)
        {
            if (DialogResult == DialogResult.OK)
            {
                _root.UserSettings.CheckIn();
                _root.ImportExcludes.CheckIn();
            }
            else
            {
                _root.UserSettings.Revert();
                _root.ImportExcludes.Revert();
            }

            if (tvMain.SelectedNode != null)
            {
                using (_root.MachineSettings.Edit())
                {
                    _root.MachineSettings.LastOptionsNode = tvMain.SelectedNode.Text;
                }
            }

            _root.HotkeysManager.RegisterAll();
        }
    }
}
